package com.agile.leetcode.concurrent.threadlocal;

import org.junit.Test;

import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * threadLocal我线程绑定变量的演示
 * threadLocal中的key是弱引用，在垃圾回收时会被回收，如果不value 不remove会导致一直占用内存而会内存泄漏
 *
 * @Author KD
 * @Date 2021/1/13 14:37
 */
@SuppressWarnings("all")
public class ThreadLocalDemo {
    // 创建本地线程变量,静态变量，全局唯一
    static ThreadLocal<String> threadLocal = new ThreadLocal<>();
    static InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal();

    /**
     * 每个线程会绑定自己的字符串，不会有线程安全问题
     * 但是用完后及时清除，防止内存泄漏
     *
     * @return
     */
    public synchronized String getStr() {
        // 打印线程名称
        System.out.println(Thread.currentThread().getName());
        // 获取值
        String s = threadLocal.get();
        if (s == null) {
            s = generateStr();
            threadLocal.set(s);
        }
        return s;
    }

    private String generateStr() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * threadLocal为每个线程赋值
     *
     * @throws InterruptedException
     */
    @Test
    public void test() throws InterruptedException {
        ThreadLocalDemo demo = new ThreadLocalDemo();
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(() -> {
            System.out.println(demo.getStr());
        });
        TimeUnit.SECONDS.sleep(5);
        executorService.submit(() -> {
            System.out.println(demo.getStr());

        });

    }

    /**
     * threadLocal的不继承性的演示
     * inheritableThreadLocal的继承性演示
     *
     * @throws Exception
     */
    @Test
    public void test1() throws Exception {
        ThreadLocalDemo demo = new ThreadLocalDemo();
        // 主线程赋值
        demo.threadLocal.set("czk");
        demo.inheritableThreadLocal.set("nzq");
        new Thread(() -> {
            // 获取值
            // 由于threadLocal的不继承性（不继承父线程的threadLocal变量的值），所以获取null
            System.out.println(demo.threadLocal.get());
            // inheritableThreadLocal具有继承性，会继承父线程的inheritableThreadLocal的值
            System.out.println(demo.inheritableThreadLocal.get());
        }).start();

        for (;;){}
    }
}
